#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "clib_type.h"
#include "clib_log.h"
#include "clib_spinlock.h"

typedef struct clib_log
{
    i08_t           name[256];
    FILE            *fh;
    log_level_t     level;
    u32_t           max_size;
    u32_t           cur_size;  
    clib_spinlock_t lock;
    u32_t           type;
} clib_log_t;

static clib_log_t clib_log[LOG_MAX_TYPE] = { 0 };

i32_t
clib_log_init(const i08_t* file, u32_t type, log_level_t level) 
{
    i32_t length;
    if(type >= LOG_MAX_TYPE) {
        return -1;
    }
    clib_log_t *log = &clib_log[type];

    if(log->fh) {
        return -1;
    }

    length = strlen(file);

    if(length >= 255) {
        return -1;
    }

    memcpy(log->name, file, length + 1);

    log->fh = fopen(file, "a+");

    if(!log->fh) {
        return -1;
    }

    log->type = type;

    clib_spinlock_init(&log->lock);

    log->level = level;
    /** TODO 内置大小 **/
    
    return 0;
}

void
clib_set_log_level(i32_t type, log_level_t level) {

    if(type >= LOG_MAX_TYPE) {
        return;
    }
    clib_log_t *log = &clib_log[type];

    log->level = level;
}

i32_t
clib_log_write(i32_t type, log_level_t level, const i08_t *fmt, ...) 
{
    va_list         ap;
    int             n, pos;
    time_t          sec;
    char            errstr[2048];
    char            err_log_time[128];
    int             lcore_id;
    struct tm       now, *t;
    struct timeval  tv;

    clib_log_t *log = &clib_log[type];

    if (level > log->level || !log->fh) {
        return 0;
    }
    /** TODO thread id **/
    lcore_id = 0;
    //lcore_id = rte_lcore_id();

    gettimeofday(&tv, NULL);
    sec = tv.tv_sec;

    t = localtime(&sec);
    now = *t;
    now.tm_mon++;
    now.tm_year += 1900;

    snprintf(err_log_time, sizeof(err_log_time),
             "%4d/%02d/%02d %02d:%02d:%02d",
             now.tm_year, now.tm_mon,
             now.tm_mday, now.tm_hour,
             now.tm_min, now.tm_sec);

    n = snprintf(errstr, sizeof(errstr), "[%s] [%s] [%s=%03d]#: ",
                 err_log_time,
                 //cnet_log_levels[level],
                 "level",
                 "lcoreid",
                 lcore_id);
    pos = n;

    va_start(ap, fmt);

    n = vsnprintf(&errstr[pos], sizeof(errstr) - n, fmt, ap);
    
    pos += n;
    
    if (pos >= sizeof(errstr)) {
        pos = sizeof(errstr) - 1;
    }

    va_end(ap);

    errstr[pos + 1] = '\0';
    log->cur_size += pos;

    fwrite(errstr,1,pos,log->fh);

    log->cur_size += pos;
    /** TODO 日志 轮转 **/

    return pos;
}
